package com.spc.car.service.project.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.spc.car.common.exception.CustomException;
import com.spc.car.common.utils.StringUtils;
import com.spc.car.data.domain.project.dto.ProjectRoleDTO;
import com.spc.car.data.domain.project.po.ProjectTeamAddBatchPO;
import com.spc.car.data.domain.project.po.ProjectTeamPO;
import com.spc.car.data.domain.project.po.ProjectTeamQueryOutsiderPO;
import com.spc.car.data.domain.project.po.ProjectTeamQueryPO;
import com.spc.car.data.domain.project.vo.ProjectMemberVO;
import com.spc.car.data.entity.project.ProjectRole;
import com.spc.car.data.entity.project.ProjectTeam;
import com.spc.car.data.entity.sys.SysUser;
import com.spc.car.data.service.project.ProjectRolePermissionService;
import com.spc.car.data.service.project.ProjectRoleService;
import com.spc.car.data.service.project.ProjectTeamService;
import com.spc.car.service.project.BidProjectTeamService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.ListUtils;
import org.apache.logging.log4j.util.Strings;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Service
public class BidProjectTeamServiceImpl implements BidProjectTeamService {

    @Autowired
    private ProjectTeamService projectTeamService;

    @Autowired
    private ProjectRoleService projectRoleService;

    @Autowired
    private ProjectRolePermissionService rolePermissionService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean addBatchMember(@NotNull ProjectTeamAddBatchPO addBatchPO,
                                  List<Integer> roleIds) {
        List<ProjectTeam> existMemberList = projectTeamService
                .listByProjectCode(addBatchPO.getProjectTenderingCode(), roleIds);

        if (CollectionUtils.isEmpty(addBatchPO.getMemberList())) {
            if (CollectionUtils.isEmpty(existMemberList)) {
                return true;
            } else {
                projectTeamService.removeByIds(existMemberList.stream()
                        .map(ProjectTeam::getProjectRoleId)
                        .collect(Collectors.toList()));
                return true;
            }
        }

        List<String> existMemberAccList = existMemberList.stream()
                .map(ProjectTeam::getUserAccount).distinct().collect(Collectors.toList());

        List<String> newMemberAccList = addBatchPO.getMemberList().stream()
                .map(ProjectTeamPO::getUserAccount).distinct().collect(Collectors.toList());

        List<String> subtractList = ListUtils.subtract(existMemberAccList, newMemberAccList);
        List<ProjectTeam> projectTeamList = new ArrayList<>();
        List<Long> removeIdList = new ArrayList<>();
        if (!CollectionUtils.isEmpty(subtractList)) {
            existMemberList.forEach(member -> {
                if (subtractList.contains(member.getUserAccount())) {
                    removeIdList.add(member.getId());
                }
            });
        }
        if (!CollectionUtils.isEmpty(removeIdList)) {
            projectTeamService.removeByIds(removeIdList);
        }

        for (ProjectTeamPO po : addBatchPO.getMemberList()) {
            List<ProjectTeam> sameList = existMemberList.stream()
                    .filter(member -> member.getUserAccount().equals(po.getUserAccount()))
                    .collect(Collectors.toList());

            ProjectTeam projectTeam = CollectionUtils.isEmpty(sameList) ? new ProjectTeam() : sameList.get(0);
            BeanUtils.copyProperties(po , projectTeam);

            projectTeam.setProjectTenderingCode(addBatchPO.getProjectTenderingCode());
            projectTeamList.add(projectTeam);
        }

        return projectTeamService.saveOrUpdateBatch(projectTeamList);
    }

    @Override
    public List<ProjectTeam> listTeamMember(@NotNull ProjectTeamQueryPO queryPO) {
        List<ProjectTeam> projectTeamList = projectTeamService.list(queryPO.toWrapper());

        if (!CollectionUtils.isEmpty(projectTeamList)
                && StringUtils.isNotBlank(queryPO.getPermissions())) {
            List<String> needPermissionList = queryPO.listPermission();
            List<ProjectRoleDTO> roleDTOList = projectRoleService.listWithPermission();

            return  projectTeamList.stream().filter(member -> {
                Optional<ProjectRoleDTO> projectRoleDTO = roleDTOList.stream()
                        .filter(roleDTO -> roleDTO.getId().equals(member.getProjectRoleId()))
                        .findFirst();
                String permission = Strings.EMPTY;
                if (projectRoleDTO.isPresent()) {
                    permission = String.join(",",
                            projectRoleDTO.get().getPermission(),
                            member.getProjectPermission());
                } else {
                    permission = member.getProjectPermission();
                }

                if (StringUtils.isNotBlank(permission)) {
                    List<String> intersectionList = ListUtils.intersection(
                            Arrays.asList(permission.split(",")),
                            needPermissionList);
                    return !CollectionUtils.isEmpty(intersectionList);
                }
                return false;
            }).collect(Collectors.toList());
        }
        return projectTeamList;
    }

    @Override
    public List<ProjectTeam> listTeamMemberOutsider(ProjectTeamQueryOutsiderPO queryOutsiderPO) {
        List<ProjectTeam> projectTeamList = projectTeamService.list(queryOutsiderPO.toWrapper());

        if (!CollectionUtils.isEmpty(projectTeamList)
                && StringUtils.isNotBlank(queryOutsiderPO.getPermissions())) {
            List<String> needPermissionList = queryOutsiderPO.listPermission();
            List<ProjectRoleDTO> roleDTOList = projectRoleService.listWithPermission();

            return projectTeamList.stream().filter(member -> {
                Optional<ProjectRoleDTO> projectRoleDTO = roleDTOList.stream()
                        .filter(roleDTO -> roleDTO.getId().equals(member.getProjectRoleId()))
                        .findFirst();
                String permission = Strings.EMPTY;
                if (projectRoleDTO.isPresent()) {
                    permission = String.join(",",
                            projectRoleDTO.get().getPermission(),
                            member.getProjectPermission());
                } else {
                    permission = member.getProjectPermission();
                }

                if (StringUtils.isNotBlank(permission)) {
                    List<String> intersectionList = ListUtils.intersection(
                            Arrays.asList(permission.split(",")),
                            needPermissionList);
                    return !CollectionUtils.isEmpty(intersectionList);
                }
                return false;
            }).collect(Collectors.toList());
        }
        return projectTeamList;
    }

    @Override
    public boolean isTeamMember(@NotNull String projectTenderingCode,
                                @NotBlank String operators,
                                String permissions) {
        boolean result = false;

        List<ProjectMemberVO> memberVOList = projectTeamService.listMember(projectTenderingCode);
        if (!CollectionUtils.isEmpty(memberVOList)
                && StringUtils.isNotBlank(operators)) {
            List<String> operatorAccList = Arrays.asList(operators.split(","))
                    .stream()
                    .distinct()
                    .collect(Collectors.toList());
            List<String> memberAccList = memberVOList.stream()
                    .map(ProjectMemberVO::getUserName)
                    .distinct()
                    .collect(Collectors.toList());

            result = memberAccList.containsAll(operatorAccList);
            if (result && StringUtils.isNotBlank("")) {
                result = havePermission(
                        memberVOList.stream()
                        .filter(member -> operatorAccList.contains(member.getUserName()))
                                .collect(Collectors.toList()),
                        permissions);
            }
        }
        return result;
    }

    @Override
    public List<String> listMemberPermission(@NotBlank String projectTenderingCode,
                                             @NotBlank SysUser user) {
        QueryWrapper condition = new QueryWrapper();
        condition.eq("project_tendering_code", projectTenderingCode);
        condition.eq("user_account", user.getUserName());

        ProjectTeam member = projectTeamService.getOne(condition);
        if (Objects.isNull(member)) {
            throw new CustomException("当前用户非项目组成员");
        }
        List<String> rolePermissionList = rolePermissionService.listPermission(member.getProjectRoleId());
        if (StringUtils.isNotBlank(member.getProjectPermission())) {
            if (CollectionUtils.isEmpty(rolePermissionList)) {
                rolePermissionList = new ArrayList<>();
            }
            rolePermissionList.addAll(
                    Arrays.asList(
                            member.getProjectPermission().split(",")));

        }
        return rolePermissionList.stream()
                .distinct().collect(Collectors.toList());
    }

    @Override
    public boolean havePermission(@NotBlank String projectTenderingCode,
                                  @NotBlank String userAccount, String permission) {
        ProjectTeam projectTeam = projectTeamService.getOne(
                new QueryWrapper<ProjectTeam>()
                        .eq("project_tendering_code", projectTenderingCode)
                        .eq("user_account", userAccount)
        );
        if (Objects.isNull(projectTeam)) {
            return false;
        }

        List<ProjectRoleDTO> roleDTOList = projectRoleService.listWithPermission();

        return havePermission(
                roleDTOList.stream()
                  .filter(projectRoleDTO -> projectTeam.getProjectRoleId().equals(projectRoleDTO.getId()))
                  .findFirst(),
                projectTeam.getProjectPermission(),
                permission);
    }

    public boolean havePermission(List<ProjectMemberVO> memberVOList,
                                  String permissions) {
        boolean result = false;
        if (!CollectionUtils.isEmpty(memberVOList)
                && StringUtils.isNotBlank(permissions)) {
            List<ProjectRoleDTO> roleDTOList = projectRoleService.listWithPermission();
            for(ProjectMemberVO member: memberVOList) {
                Optional<ProjectRoleDTO> projectRoleDTO = roleDTOList.stream()
                        .filter(roleDTO -> roleDTO.getId().equals(member.getProjectRoleId()))
                        .findFirst();

                if (!havePermission(projectRoleDTO, member.getProjectPermission(), permissions)) {
                    return false;
                }

            }
            result = true;
        }

        return result;
    }

    public boolean havePermission(Optional<ProjectRoleDTO> projectRoleDTO,
                                  String projectPermission,
                                  String requiredPremissions) {
        boolean result = false;
        if (StringUtils.isBlank(requiredPremissions)) {
            return true;
        }
        List<String> requiredPermissionList = Arrays.asList(requiredPremissions.split(","));

        String permission = Strings.EMPTY;
        if (projectRoleDTO.isPresent()) {
            permission = String.join(",",
                    projectRoleDTO.get().getPermission(),
                    projectPermission);
        } else {
            permission = projectPermission;
        }

        if (StringUtils.isNotBlank(permission)) {
            List<String> permissionList = Arrays.asList(permission.split(","));

            //result = permissionList.containsAll(requiredPermissionList);
            result = CollectionUtils.containsAny(permissionList, requiredPermissionList);

        }

        return result;
    }

    @Override
    public List<ProjectRole> listSuitRole(String projectTenderingCode,
                                          String userAccount) {
        List<ProjectRole> result = new ArrayList<>();

        if (StringUtils.isNotBlank(projectTenderingCode)
                && StringUtils.isNotBlank(userAccount) ) {
            QueryWrapper condition = new QueryWrapper();
            condition.eq("project_tendering_code", projectTenderingCode);
            condition.eq("user_account", userAccount);

            ProjectTeam projectTeam = projectTeamService.getOne(condition);
            if (Objects.isNull(projectTeam)) {
                return result;
            }


            QueryWrapper<ProjectRole> roleCondition = new QueryWrapper<>();
            if (1 == projectTeam.getProjectRoleId().intValue()) {
                roleCondition.ne("id", 10);
            } else if (2 == projectTeam.getProjectRoleId().intValue()) {
                roleCondition.eq("id", 3);
            } else {
                roleCondition.eq("id", projectTeam.getProjectRoleId());
            }

            result = projectRoleService.list(roleCondition);
        } else {
            result = projectRoleService.list();
        }

        return result;
    }
}
